package bean;

import utils.Logger;

import java.io.*;
import java.util.HashMap;
import java.util.Map;

public class Request {

    private InputStream inputStream;
    private String protocol="";
    private String method="";
    private String requestUrl ="";
    private String remoteIP;
    private String localIP;
    private  boolean isOK = false;

    private Map<String, byte[]> formData = new HashMap<>();
    private Map<String,String> attributes = new HashMap<>();


    public Request(InputStream inputStream) throws Exception {
        this.inputStream = inputStream;
        init();
    }

    public void init() throws Exception {

        BufferedReader bufferedReader = new BufferedReader(new InputStreamReader(inputStream));

        String line = bufferedReader.readLine();
        if(line == null ){
            return;
        }

        String []args = line.split(" ");
        if(args.length !=3){
            throw new Exception("错误协议");
        }

        method = args[0];
        requestUrl = args[1];
        protocol = args[2];
        while(true){
            line = bufferedReader.readLine();
            if(line == null)break;
            line = line.trim();
            if(line.isEmpty()){
                break;
            }
            args = line.split(":");
            String keys = args[0].trim().toLowerCase();
            String value = args[1].trim();
            attributes.put(keys, value);
        }

        parseUrlParam();
        solveFormData(bufferedReader);
        isOK = true;
    }



    public String toString(){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(method);
        stringBuilder.append(" ");
        stringBuilder.append(requestUrl);
        stringBuilder.append(" ");
        stringBuilder.append(protocol);
        stringBuilder.append("\r\n");
        attributes.entrySet().forEach((e)->{
            stringBuilder.append(e.getKey());
            stringBuilder.append(" : ");
            stringBuilder.append(e.getValue());
            stringBuilder.append("\r\n");
        });
        return stringBuilder.toString();
    }

    public InputStream getInputStream() {
        return inputStream;
    }

    public void setInputStream(InputStream inputStream) {
        this.inputStream = inputStream;
    }

    public String getProtocol() {
        return protocol;
    }

    public void setProtocol(String protocol) {
        this.protocol = protocol;
    }

    public String getMethod() {
        return method;
    }

    public void setMethod(String method) {
        this.method = method;
    }

    public String getRequestUrl() {
        return requestUrl;
    }

    public void setRequestUrl(String requestUrl) {
        this.requestUrl = requestUrl;
    }

    public void  setAttributes(String key,String values){
        this.attributes.put(key,values);
    }

    public String getAttribute(String key){
        return this.attributes.get(key);
    }

    public boolean isOK() {
        return isOK;
    }

    public void setOK(boolean OK) {
        isOK = OK;
    }

    public String toHeader(){
        StringBuilder stringBuilder = new StringBuilder();
        stringBuilder.append(method);
        stringBuilder.append(" ");
        stringBuilder.append(requestUrl);
        stringBuilder.append(" ");
        stringBuilder.append(protocol);
        stringBuilder.append(" from ip : ");
        stringBuilder.append(remoteIP);
        stringBuilder.append("\r\n");
        return stringBuilder.toString();
    }


    public String getRemoteIP() {
        return remoteIP;
    }

    public void setRemoteIP(String remoteIP) {
        this.remoteIP = remoteIP;
    }

    public String getLocalIP() {
        return localIP;
    }

    public void setLocalIP(String localIP) {
        this.localIP = localIP;
    }

    public void solveFormData(BufferedReader inputStream){
        String contentType = attributes.get("content-type");
        if(contentType == null){
            return ;
        }
        switch (contentType){
            case  "application/x-www-form-urlencoded": parseApplicationUrlencodeFormData(inputStream);break;
            case "multipart/form-data": parseMultipartFormData(inputStream);break;
            case "application/json" : parseJSonData(inputStream);break;
            default: ignoreData(inputStream);
        }
    }

    public void parseApplicationUrlencodeFormData(BufferedReader inputStream){
            if("POST".equals(method)){
                try {
                    String contentLength = attributes.get("content-length");
                    if(contentLength == null){
                        return;
                    }
                    char[]data = new char[Integer.valueOf(contentLength)];
                    inputStream.read(data);
                    String line = new String(data);
                    if(line == null){
                        return;
                    }
                    paramParse(line);
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
    }

    public void parseMultipartFormData(BufferedReader inputStream){
        return;
    }

    public void parseJSonData(BufferedReader inputStream){
        return;
    }

    public void ignoreData(BufferedReader inputStream){
        return;
    }

    public void paramParse(String params){
        String []parmsValue = params.split("&");
        for(String entity : parmsValue){
            String []keyValue = entity.split("=");
            if(keyValue.length ==2){
                formData.put(keyValue[0],keyValue[1].getBytes());
            }
        }
    }
    public void parseUrlParam(){
        int index = requestUrl.indexOf("?");
        if (index != -1 && index != requestUrl.length() - 1) {
            String params = requestUrl.substring(index + 1);
            paramParse(params);
        }
    }

    public String getParam(String key) {
        byte[]data = formData.get(key);
        if (data == null) {
            return "";
        } else {
            return new String(data);
        }
    }

    public byte[] getRawParam(String key){
        return formData.get(key);
    }
}
